package cn.com.pansky.action.bank;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.com.pansky.payment.PayConf;
import cn.com.pansky.sdk.API;
import cn.com.pansky.util.AppUtils;
import cn.com.pansky.util.DateUtil;
import cn.com.pansky.util.EctractZip;
import cn.com.pansky.util.HttpClientUtil;
import cn.com.pansky.util.PropertiesUtil;
import cn.com.pansky.util.RequestUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 建行对账文件下载异步通知
 * @author Administrator
 *
 */
public class RecvDownLoadNotify extends HttpServlet {

	private static final long serialVersionUID = 1L;
	protected static Logger logger = LoggerFactory
			.getLogger(RecvDownLoadNotify.class);

	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doPost(req, resp);
	};

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		resp.setStatus(HttpServletResponse.SC_OK);// 响应清算平台通知
		String fileName = "";
		// 获取通知参数
		Map<String, String> respMap = RequestUtils.getReqMap(req);
		// 转换编码
		if (null != respMap.get("fileName")) {
			fileName = respMap.get("fileName");
			if (StringUtils.isNotBlank(fileName)) {
				respMap.put(
						"fileName",
						new String(fileName.getBytes("ISO8859-1"), respMap
								.get("charset")));
			}
		}
		if (null != respMap.get("reqReserved")) {
			String reqReserved = respMap.get("reqReserved");
			if (StringUtils.isNotBlank(reqReserved)) {
				respMap.put(
						"reqReserved",
						new String(reqReserved.getBytes("ISO8859-1"), respMap
								.get("charset")));
			}
		}
		String merId = respMap.get("merId"); // 获取商户号
		// 建行根据商户号获取秘钥
		JSONArray array = API.getAAE051OrSignkey(merId);
		JSONObject obj = JSONObject.parseObject(array.get(0).toString());
		String signkey = obj.getString("BAE300");
		// 签名验证
		boolean validate = AppUtils.validate(respMap, signkey, respMap.get("charset"));
		if (validate) {
			// 此处添加商户业务处理逻辑
			if ("1".equals(respMap.get("fileStatus"))) {
				System.out.println("建行对账文件下载成功.");
				downLoad(req, resp, respMap, signkey);
			} else if ("2".equals(respMap.get("fileStatus"))) {
				System.out.println("建行对账文件下载失败.");
			}
		} else {
			System.out.println("建行对账文件下载签名验证失败.");
		}
	}

	public void downLoad(HttpServletRequest req, HttpServletResponse resp, Map<String, String> respMap, String signkey) {
		Map<String, String> paramMap = new HashMap<String, String>();
		paramMap.put("version", PayConf.PAY_VERSION);
		paramMap.put("charset", PayConf.CHARSET);
		paramMap.put("signMethod", PayConf.SIGNMETHOD);
		paramMap.put("transCode", "F002"); // 文件下载
		paramMap.put("merId", respMap.get("merId")); // 商户号
		paramMap.put("billDate", respMap.get("billDate")); // 对账日期
		paramMap.put("billType", "02"); // 对账单类型
		paramMap.put("fileType", "01"); // 对账单格式
		paramMap.put("transTime", DateUtil.currentTime());
		paramMap.put("fileName", respMap.get("fileName")); // 下载文件名
		// 签名信息
		String[] paramKeys = new String[] {"version", "charset", "signMethod",
				"transCode", "merId", "billDate", "billType", "fileType",
				"transTime", "fileName"};// 构造签名参数数组
		Map<String, String> paraMap = AppUtils.prepareDataMap(paramMap,
				paramKeys);// 数据预处理
		String mac = AppUtils.signBeforePost(paraMap, signkey, PayConf.CHARSET);
		paraMap.put("sign", mac);

		System.out.println("向清算平台发送交易查询请求:" + AppUtils.restMapToStr(paraMap));// 请求报文
		String res = HttpClientUtil.httpPost(PayConf.DOWNLOAD_URL, paraMap, PayConf.CHARSET);
		System.out.println("清算平台同步响应:" + res);// 返回的响应报文

		// 签名验证
		boolean validate = AppUtils.validate(res, signkey, paraMap.get("charset"));
		if (validate) {
			Map<String, String> resMap = new HashMap<String, String>();
			AppUtils.convertRetToMap(res, resMap);
			if ("00".equals(resMap.get("respCode"))) {
				String fileContent = resMap.get("fileContent");
				try {
					// 写入本地
					byte[] base64RespByte = new Base64().decode(fileContent);
					File file = new File(PropertiesUtil.getValue("filePath") + respMap.get("fileName"));
					FileOutputStream fos = new FileOutputStream(file);
					fos.write(base64RespByte);
					fos.flush();
					fos.close();

					EctractZip z = new EctractZip();
					ArrayList<String> fileList = z.Ectract(file.getPath(),
							PropertiesUtil.getValue("filePath") + "unzip"); // 返回解压缩出来的文件列表
					readFile(file, fileList);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 读取文件
	 * @param file
	 * @param a
	 * @throws UnsupportedEncodingException
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private void readFile(File file, ArrayList<String> fileList)
			throws UnsupportedEncodingException, FileNotFoundException,
			IOException {
		JSONArray resultArray = new JSONArray();
		for (String f : fileList) {
			File file1 = new File(f);
			if (file1.isFile() && file1.exists()) { // 判断文件是否存在
				InputStreamReader read = new InputStreamReader(
						new FileInputStream(file1), "utf-8");// 考虑到编码格式
				BufferedReader bufferedReader = new BufferedReader(read);
				String lineTxt = null;
				int i = 0;
				while ((lineTxt = bufferedReader.readLine()) != null) {
					//序号|商户号|商户名称|商户订单号|流水号|支付类型|支付银行|支付金额|退款金额|支付时间|记账日期|交易状态|支付渠道|终端类型|交易自定义域
					//1|10001|西安融联网络科技有限公司|2016110883434|J100010106620161108120248402|B2C|中国建设银行|0.20|0.00|2016-11-08 12:02:48|2016-11-08|交易成功|网银支付|网页|
					if(i > 0) {
						JSONObject obj = new JSONObject();
						String items = lineTxt.replace("|", ",");
						String[] itemsArray = items.split(",");
						if(itemsArray[11] != null && !itemsArray[11].toString().equals("") && itemsArray[11].toString().equals("交易成功")) {
							Date date = null;
							try {
								date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(itemsArray[9].toString());
							} catch (ParseException e) {
								e.printStackTrace();
							}
							obj.put("AAD017", new SimpleDateFormat("yyyyMMdd").format(date)); // 交易日期
							obj.put("AAZ288", itemsArray[3].trim()); // 订单号
							obj.put("AAD008", itemsArray[4].trim()); // 平台流水号
							obj.put("AAE051", itemsArray[1].trim()); // 商户号
							obj.put("AAE019", itemsArray[7].trim()); // 交易金额
							obj.put("AAE354", "1"); // 回应码
							obj.put("AAE355", ""); // 错误信息
							obj.put("AAC002", ""); // 身份证号
							obj.put("AAZ295", "JH"); // 银行支付类别
							obj.put("AAE356", "0"); // 退款标识
							obj.put("AAZ2881", ""); // 邮储订单号
							obj.put("AAC003", "");
							// 判断订单号中是否包含字母，将包含字母的订单排除
							boolean res = false;
							for(int j = 0; j < itemsArray[3].trim().length(); j++) {
								if(Character.isLetter(itemsArray[3].trim().charAt(j))) {
									res = true;
									break;
								}
							}
							if(!res) {
								resultArray.add(obj); // 将每一笔订单存入array中
							}
							// 保存对账信息至RA22表中
//							BankStatementService state = new BankStatementService();
//							state.insertRA22(map);
						}
					}
					i++;
				}
				read.close();
				file1.delete(); // 删除对账临时文件
			}
		}
		// 调用业务接口，将订单保存在业务表中
		API.insertSysRA22(resultArray);
	}

}
